﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace WindowsFormsApplication1
{
    class ParseAVE
    {
        String m_InputPath = null;

        String m_OutputPath = null;

        //the spliters 
        char[] m_DelimiterChars = { ' ', ',',';' };

        char[] m_FilteredChars = { '\r','\n','\t'};

        //The basic modelling unit in DVE is a system, which is composed of processes.
        String m_KeyProcess = "process";

        //byte A[9];
        //int i,j;
        //variables
        String m_VarType1 = "byte";
        String m_VarType2 = "int";

        //constants
        //const byte k = 3;
        String m_Cons = "const";

        //state
        String m_State = "state";

        //iniation
        String m_Init = "init";

        //transitions
        String m_Trans = "trans";

        //Global Definitions 
        String m_Define = "#define";

        
        AVEStructure m_readAVE = new AVEStructure();

        Process m_process = null;

        public ParseAVE() { }

        public void setPath(String input, String output)
        {

            this.m_InputPath = input;
            this.m_OutputPath = output;
        }

        public AVEStructure parse()
        {

            String input = getFileAsString(m_InputPath);

            input = input.Trim();
            input = input.Replace("\r", "");
        //    globaldefine = globaldefine.Replace("\n", "");
            input = input.Replace("\t", "");

            int first = -1;
            first = input.IndexOf(m_KeyProcess);

            //parse the global variables
            String globaldefine = input.Substring(0, first);

            globaldefine = globaldefine.Replace("\n", "");
            String[] globalvariable = globaldefine.Split(';');


            //save 
            for (int i = 0; i < globalvariable.Length - 1; i++)
            {
                m_readAVE.globalvaris.Add(globalvariable[i]);
            }

            // start to parse the process
            while (first != -1)
            {
                String tempInput = input.Substring(first + m_KeyProcess.Length);
                int end = tempInput.IndexOf(m_KeyProcess);
                if (end == -1)
                {
                    end = tempInput.IndexOf("system");
                }
                String proc = tempInput.Substring(0, end);
                parseProcesses(proc);

                input = input.Substring(end);
                first = input.IndexOf(m_KeyProcess);
            }

            return m_readAVE;

        }


        public void parseProcesses(String proc)
        {

            //            foreach (string s in words)
            //            {
            //                System.Console.WriteLine(s);
            //            }

            m_process = new Process();

            while (proc != null)
            {
                //see if it is a constants
                if (proc.IndexOf(m_Cons) != -1)
                {

                    String subconstants = proc.Substring(proc.IndexOf(m_Cons), proc.IndexOf(';'));

                    parseConstants(subconstants);

                    proc = proc.Substring(proc.IndexOf(';') + 1);
                    continue;
                }

                // see if it is a normal varibles
                if ((proc.IndexOf(m_VarType1) != -1) || (proc.IndexOf(m_VarType2) != -1))
                {
                    String subvar = proc.Substring(proc.IndexOf(m_VarType1), proc.IndexOf(';'));

                    parseVariables(subvar);

                    proc = proc.Substring(proc.IndexOf(';') + 1);
                    continue;
                }

                // see if it is a state;
                if (proc.IndexOf(m_State) != -1)
                {

                    String substate = proc.Substring(proc.IndexOf(m_State), proc.IndexOf(';'));
                    String[] states = substate.Split(m_DelimiterChars);
                    for (int i = 0; i < states.Length; i++)
                    {

                        //write the csp
                        if(states[i] != ""){
                            m_process.states.Add(states[i]);
                        }

                    }
                    proc = proc.Substring(proc.IndexOf(';') + 1);
                    continue;
                }

                // se if it is a init
                if (proc.IndexOf(m_Init) != -1)
                {

                    String subinit = proc.Substring(proc.IndexOf(m_Init), proc.IndexOf(';'));
                    String[] inits = subinit.Split(m_DelimiterChars);

                    m_process.init = inits[1];

                    proc = proc.Substring(proc.IndexOf(';') + 1);
                    continue;
                }


                if (proc.IndexOf(m_Trans) != -1)
                {

                    String subtrans = proc.Substring(proc.IndexOf(m_Trans));

                    parseTransitions(subtrans);

                    proc = proc.Substring(proc.IndexOf(m_Trans) + subtrans.Length);
                    continue;
                }

                break;
            }

            m_readAVE.ps.Add(m_process);

            m_process = null;


        }

        public void parseVariables(String vari)
        {


            String[] vars = vari.Split(m_DelimiterChars);
            for (int i = 0; i < vars.Length; i++)
            {
                //write the csp
                m_process.localvaris.Add(vars[i]);

            }
        }


        public void parseConstants(String constants)
        {

            if ((constants.IndexOf(m_VarType1) != -1) || (constants.IndexOf(m_VarType2) != -1))
            {
                String subsubvar = constants.Substring(constants.IndexOf(m_VarType1), constants.IndexOf(';'));
                String[] vars = subsubvar.Split(m_DelimiterChars); // one-name one-value

                for (int i = 0; i < vars.Length; i++)
                {

                    //write the csp
                    m_process.constantvaris.Add(vars[i]);
                }

            }

        }

        public void parseTransitions(String transition)
        {
            //read by line 
            String[] lines = transition.Split('\n');

            //ignore the first sentence which is trans, jump to the second one

            for (int i = 1; i < lines.Length - 2; i++)
            {

                m_process.Trans.expressions.Add(lines[i]);

            }

        }

        public void parseAssertions(String assertions)
        {


        }

        public String getFileAsString(string fileName)
        {
            StreamReader sReader = null;
            String contents = null;
            try
            {
                FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                sReader = new StreamReader(fileStream);
                contents = sReader.ReadToEnd();
            }
            finally
            {
                if (sReader != null)
                {
                    sReader.Close();
                }
            }
            return contents;
        }

       
    }
}
